#include "NoBlockPoller.h"
#include <chrono>
#include <map>
#include <poll.h>
#include <sys/select.h>
#include <thread>
#include "DateTime.h"
#include "EventLoop.h"
#include "ThreadChannel.h"
#include "TimerChannel.h"
#include "WakeupChannel.h"
#include "XnccEventfd.h"

namespace xncc {
namespace foundation {
    NoBlockPoller::NoBlockPoller()  = default;
    NoBlockPoller::~NoBlockPoller() = default;

    void NoBlockPoller::addChannel(const std::shared_ptr<Channel>& chnl)
    {
        Poller::addChannel(chnl);
        if (chnl->Type() == ChannelType::THREAD_CHANNEL) {
            auto threadCh                        = std::dynamic_pointer_cast<ThreadChannel>(chnl);
            threadChannels_[threadCh->queueId()] = chnl;
        }
        else {
            channels_[chnl->fd()] = chnl;
            // 只服务业务线程 处理的channel 只有时间 wakeup 以及eventfd 初始化完成之后就不会再变更
        }
    }
    void NoBlockPoller::removeChannel(const std::shared_ptr<Channel>& chnl) { Poller::removeChannel(chnl); }
    void NoBlockPoller::updateChannel(const std::shared_ptr<Channel>& chnl) {}
    void NoBlockPoller::loopOnce(int waitUs)
    {
        for (const auto& ele : channels_) {
            if (ele.second->Type() == ChannelType::WAKEUP_CHANNEL) {
                auto chnl = std::dynamic_pointer_cast<WakeupChannel>(ele.second);
                chnl->doPendingFuncs();
            }
            else if (ele.second->Type() == ChannelType::TIMER_CHANNEL) {
                auto chnl = std::dynamic_pointer_cast<TimerChannel>(ele.second);
                if (chnl->timerSize() != 0U) {  // 线程内执行 获取size不会有问题
                    const auto now = xncc::types::DateTime::timeMicro();
                    chnl->doTimerFuncs(now);
                }
            }
        }
        for (const auto& ele : threadChannels_) {
            auto chnl = std::dynamic_pointer_cast<ThreadChannel>(ele.second);
            chnl->HandleMessages(true);
        }
        if (waitUs > 0) {
            std::this_thread::sleep_for(std::chrono::microseconds(waitUs));
        }
    }
}  // namespace foundation
}  // namespace xncc